home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 26
/
Cream of the Crop 26.iso
/
os2
/
plnk081.zip
/
pilot-link.0.8.1
/
pi-csd.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-08-10
|
10KB
|
357 lines
/* pi-csd.c: Connection Service Daemon, required for accepting logons via NetSync(tm)
*
* Copyright (c) 1997, Kenneth Albanowski
*
* This is free software, licensed under the GNU Public License V2.
* See the file COPYING for details.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "pi-source.h"
#include "pi-socket.h"
#include "pi-dlp.h"
#include "pi-serial.h"
#include "pi-slp.h"
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <netdb.h>
char hostname[130];
struct in_addr address, netmask;
void Help(char *argv[])
{
fprintf(stderr,"usage:%s [options]\n",argv[0]);
fprintf(stderr,"\n <-h hostname> Name of host, used for verification");
if (strlen(hostname))
fprintf(stderr,"\n (defaults to '%s')", hostname);
else
fprintf(stderr,"\n (no default)");
fprintf(stderr,"\n <-a address> IP address of host");
if (address.s_addr)
fprintf(stderr,"\n (defaults to '%s')", inet_ntoa(address));
else
fprintf(stderr,"\n (no default)");
fprintf(stderr,"\n <-s address> Subnet mask of IP address");
if (netmask.s_addr)
fprintf(stderr,"\n (defaults to '%s')", inet_ntoa(netmask));
else
fprintf(stderr,"\n (no default)");
fprintf(stderr,"\n <-q> Quiet: turn off status messages\n");
fprintf(stderr,"\nNote: Currently the subnet mask is not used by %s.\n", argv[0]);
exit(0);
}
#ifdef HAVE_SA_LEN
#ifndef max
#define max(a,b) ((a) > (b) ? (a) : (b))
#endif
#define ifreq_size(i) max(sizeof(struct ifreq),\
sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
#else
#define ifreq_size(i) sizeof(struct ifreq)
#endif /* HAVE_SA_LEN*/
/* What, me worry? */
#ifndef IFF_POINTOPOINT
# ifdef IFF_POINTTOPOINT
# define IFF_POINTOPOINT IFF_POINTTOPOINT
# endif
#endif
/* While this function is useful in pi-csd, it is intended also to
be a demonstration of the proper (or improper, if I'm unlucky) techniques
to retrieve networking information.*/
void fetch_host(char * hostname, int hostlen, struct in_addr *address, struct in_addr * mask)
{
int s, n, i;
struct ifconf ifc;
struct ifreq * ifr, ifreqaddr, ifreqmask;
struct hostent * hent;
#ifdef HAVE_GETHOSTNAME
/* Get host name the easy way */
gethostname(hostname, hostlen);
#else
# ifdef HAVE_UNAME
struct utsname uts;
if (uname(&uts)==0) {
strncpy(hostname, uts.nodename, hostlen-1);
hostname[hostlen-1] = '\0';
}
# endif /*def HAVE_UNAME*/
#endif /*def HAVE_GETHOSTNAME*/
/* Get host address through DNS */
hent = gethostbyname(hostname);
if (hent) {
while(*hent->h_addr_list) {
struct in_addr haddr;
memcpy(&haddr, *(hent->h_addr_list++), sizeof(haddr));
if (haddr.s_addr != inet_addr("127.0.0.1"))
memcpy(address, &haddr, sizeof(haddr));
}
}
#if defined(SIOCGIFCONF) && defined(SIOCGIFFLAGS)
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s<0)
return;
ifc.ifc_buf = calloc(1024, 1);
ifc.ifc_len = 1024;
if (ioctl(s, SIOCGIFCONF, (char*)&ifc)<0)
goto done;
n = ifc.ifc_len;
for (i=0; i<n; i+=ifreq_size(*ifr)) {
struct sockaddr_in * a;
struct sockaddr_in * b;
ifr = (struct ifreq*)((caddr_t) ifc.ifc_buf+i);
a = (struct sockaddr_in*)&ifr->ifr_addr;
strncpy(ifreqaddr.ifr_name, ifr->ifr_name, sizeof(ifreqaddr.ifr_name));
strncpy(ifreqmask.ifr_name, ifr->ifr_name, sizeof(ifreqmask.ifr_name));
if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreqaddr) < 0)
continue;
/* Reject loopback device */
#ifdef IFF_LOOPBACK
if (ifreqaddr.ifr_flags & IFF_LOOPBACK)
continue;
#endif /*def IFF_LOOPBACK*/
#ifdef IFF_UP
/* Reject down devices */
if (!(ifreqaddr.ifr_flags & IFF_UP))
continue;
#endif /*def IFF_UP*/
if (ifr->ifr_addr.sa_family != AF_INET)
continue;
/* If it is a point-to-point device, use the dest address */
#if defined(IFF_POINTOPOINT) && defined(SIOCGIFDSTADDR)
if (ifreqaddr.ifr_flags & IFF_POINTOPOINT) {
if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreqaddr) < 0)
break;
a = (struct sockaddr_in*)&ifreqaddr.ifr_dstaddr;
if (address->s_addr == 0) {
memcpy(address, &a->sin_addr, sizeof(struct in_addr));
}
} else
#endif /*defined(IFF_POINTOPOINT) && defined(SIOCGIFDSTADDR)*/
/* If it isn't a point-to-point device, use the address */
#ifdef SIOCGIFADDR
{
if (ioctl(s, SIOCGIFADDR, (char *)&ifreqaddr) < 0)
break;
a = (struct sockaddr_in*)&ifreqaddr.ifr_addr;
if (address->s_addr == 0) {
memcpy(address, &a->sin_addr, sizeof(struct in_addr));
}
}
#endif /*def SIOCGIFADDR*/
/* OK, we've got an address */
/* Compare netmask against the current address and see if it seems to match. */
#ifdef SIOCGIFNETMASK
if (ioctl(s, SIOCGIFNETMASK, (char *)&ifreqmask) < 0)
break;
/*
* NetBSD probably falls into the same camp - need to check
*/
#if defined (__FreeBSD__) || defined (__NetBSD__) || defined (__EMX__)
b = (struct sockaddr_in*)&ifreqmask.ifr_addr;
#else
b = (struct sockaddr_in*)&ifreqmask.ifr_netmask;
#endif
if ((mask->s_addr == 0) && (address->s_addr != 0)) {
if ((b->sin_addr.s_addr & a->sin_addr.s_addr) == (b->sin_addr.s_addr & address->s_addr)) {
memcpy(mask, &b->sin_addr, sizeof(struct in_addr));
/* OK, we've got a netmask */
break;
}
}
#endif /*def SIOCGIFNETMASK*/
}
done:
free(ifc.ifc_buf);
close(s);
#endif /*defined(SIOCGIFCONF) && defined(SIOCGIFFLAGS)*/
}
void main(int argc, char*argv[]) {
int sockfd;
struct sockaddr_in serv_addr, cli_addr;
int clilen;
char mesg[1026];
fd_set rset;
int n;
struct in_addr raddress;
char * progname;
extern char* optarg;
extern int optind;
struct hostent * hent;
int quiet=0;
progname = argv[0];
memset(&address, 0, sizeof(address));
memset(&netmask, 0, sizeof(netmask));
hostname[0] = 0;
fetch_host(hostname, 128, &address, &netmask);
while ((n = getopt(argc, argv, "h:s:a:q")) != EOF) {
switch (n) {
case 'h':
strcpy(hostname, optarg);
break;
case 'a':
if (!inet_aton(optarg, &address))
if ((hent = gethostbyname(optarg)))
memcpy(&address.s_addr, hent->h_addr, sizeof(address));
else {
fprintf(stderr, "Invalid address '%s'\n\n", optarg);
Help(argv);
}
break;
case 's':
if (!inet_aton(optarg, &netmask))
Help(argv);
break;
case 'q':
quiet = 1;
break;
case 'H': case '?': default:
Help(argv);
}
}
if ((address.s_addr == 0) || (strlen(hostname)==0))
Help(argv); /* cannot execute without address and hostname */
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd <0 ) {
perror("Unable to get socket");
exit(1);
}
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(14237);
if (bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr))< 0) {
perror("Unable to bind socket");
exit(1);
}
if (!quiet) {
fprintf(stderr, "%s(%d): Connection Service Daemon for PalmPilot(tm) active.\n",
progname, getpid());
fprintf(stderr, "%s(%d): Accepting connection requests for '%s' at %s",
progname, getpid(),
hostname,
inet_ntoa(address)
);
fprintf(stderr, " with mask %s.\n",
inet_ntoa(netmask)
);
}
for (;;) {
clilen = sizeof(cli_addr);
FD_ZERO(&rset);
FD_SET(sockfd, &rset);
if (select(sockfd+1, &rset, 0, 0, 0)<0) {
perror("select failure");
exit(1);
}
n = recvfrom(sockfd, mesg, 1024, 0, (struct sockaddr*)&cli_addr, &clilen);
if (n<0) {
continue;
}
mesg[n] = 0;
if (!quiet) {
hent = gethostbyaddr((char*)&cli_addr.sin_addr.s_addr,4,AF_INET);
memcpy(&raddress, &cli_addr.sin_addr.s_addr, 4);
fprintf(stderr, "%s(%d): Connection from %s[%s], ",
progname,
getpid(),
hent ? hent->h_name : "",
inet_ntoa(raddress));
}
if (get_short(mesg) != 0xFADE)
goto invalid;
if ((get_byte(mesg+2) == 0x01) && (n>12)) {
struct in_addr ip, mask;
char * name = mesg+12;
memcpy(&ip, mesg+4, 4);
memcpy(&mask, mesg+8, 4);
if (!quiet) {
fprintf(stderr, "req '%s', %s",
name, inet_ntoa(ip));
fprintf(stderr, ", %s", inet_ntoa(mask));
}
if (strcmp(hostname, name)==0) {
if (!quiet)
fprintf(stderr, " = accept.\n");
set_byte(mesg+2, 0x02);
memcpy(mesg+4, &address, 4); /* address is already in motorola byte order */
n = sendto(sockfd, mesg, n, 0, (struct sockaddr*)&cli_addr, clilen);
if (n < 0) {
perror("sendto error");
}
continue;
}
if (!quiet)
fprintf(stderr, " = reject.\n");
continue;
}
invalid:
if (!quiet)
fprintf(stderr, "invalid packet of %d bytes:\n", n);
dumpdata(mesg, n);
}
}